package org.example.retry;

import com.github.rholder.retry.RetryException;
import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.github.rholder.retry.WaitStrategies;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 重试测试
 */
@Slf4j
@Component
public class RetryTest implements ApplicationRunner {
    public static void main(String[] args) {
        Handler handler = new Handler();
//        retryByLoop(handler);
        retryByGuava(handler);
    }

    /**
     * 1.使用guava重试
     *   <!--retry框架-->
     *   <dependency>
     *       <groupId>com.github.rholder</groupId>
     *       <artifactId>guava-retrying</artifactId>
     *       <version>2.0.0</version>
     *   </dependency>
     *
     * @param handler
     */
    private static void retryByGuava(Handler handler) {
        Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
                .retryIfResult((r) -> r.equals(Boolean.FALSE))// 结果为false就重试
                .retryIfExceptionOfType(BusiException.class)// 异常为BusiException就重试
                .withWaitStrategy(WaitStrategies.fixedWait(500, TimeUnit.MILLISECONDS))// 重试间隔
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))// 最大重试次数
                .build();
        try {
            retryer.call(()-> handler.handle(3));
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (RetryException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 2.使用 循环方式+代理模式 来重试
     * @param handler
     */
    private static void retryByLoop( Handler handler) {
        RetryByLoop retryByLoop = new RetryByLoop(handler, 3, 500);
        Boolean result = retryByLoop.handler(3);
        System.out.println(result);
    }

    /**
     * 3.使用Spring-Retry
     */
    @Autowired
    private RetryTestBySpring retryTestBySpring;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        try {
            Boolean result = retryTestBySpring.handle(0);
            log.info("result={}",result);
        } catch (Exception e) {
            log.error("RetryTestBySpring-err",e);
        }
    }
}
